import { BaseView } from "../base/BaseView";
import { errorMgr } from "./ErrorMgr";
import { gameMain } from "../../GameMain";
import { instantiate, Node, Prefab, resources, Widget } from "cc";
import { Views } from "../cfg/XlsxDef";
import { Xlsx } from "../cfg/Xlsx";

/**
 * 界面层级管理
 */
export const layerMgr = _ as LayerMgr;
export class LayerMgr {

    private _viewLayerDic: { [layer: number]: Node } = {};

    /** 正在加载中还未打开的界面队列 */
    private _loadingViewQueue: Views[] = [];
    /** 正在加载中还未打开的界面 */
    private _loadingViewDic: {
        [view: string]: {
            args: any[],
            layer: ViewLayer
            onOpen?: (baseView: BaseView) => any
            prefab?: Prefab
        }
    } = {};

    /** 打开中的界面 */
    private _viewDic: { [view: string]: BaseView } = {};
    /** 界面缓存 */
    private _viewCacheDic: { [view: string]: BaseView } = {};
    /** closeAll时排除的界面 */
    private _closeAllExViews = { [Views.MainView]: true, [Views.TipView]: true };

    init() {
        (layerMgr as any) = this;

        //初始化层级
        let layers = gameMain.viewLayers;
        for (let layer in ViewLayer) {
            if (!isNaN(Number(layer))) continue;
            let node = new Node("Layer-" + layer);
            let widget = node.addComponent(Widget);
            widget.top = widget.bottom = widget.left = widget.right = 0;
            widget.isAlignTop = widget.isAlignBottom = widget.isAlignLeft = widget.isAlignRight = true;
            node.layer = layers.layer;
            layers.addChild(node);
            this._viewLayerDic[ViewLayer[layer]] = node;
        }
    }

    /**
     * 获取层级节点
     * @param layer 
     * @returns 
     */
    getLayer(layer: ViewLayer) {
        return this._viewLayerDic[layer];
    }

    /**
     * 打开界面
     * @param view 
     * @param args 
     * @param layer 
     * @param onOpen 打开回调
     */
    open(view: Views, args?: any[], layer?: ViewLayer, onOpen?: (baseView: BaseView) => any) {

        if (layer === undefined) {
            layer = ViewLayer.windowTop;
            let cfg = Xlsx.view.get(Views[view]);
            if (cfg && cfg.layer != undefined) {
                layer = cfg.layer;
            }
        }
        if (!this.getLayer(layer)) return errorMgr.error("界面打开失败：层级错误");

        let loading = this._loadingViewDic[view];
        if (loading) {
            loading.args = args;
            loading.layer = layer;
            loading.onOpen = onOpen;
            return;
        }

        this._loadingViewQueue.push(view);
        loading = this._loadingViewDic[view] = { args, layer, onOpen };
        if (this._viewDic[view] || this._viewCacheDic[view]) {
            this.onViewLoaded(view);
        } else {
            resources.load("views/" + view, Prefab, (err, prefab) => {
                if (err) {
                    this.clearLoadingView(view);
                    this.openNext();
                    return errorMgr.error("界面打开失败：层级错误");
                }
                this.onViewLoaded(view, prefab);
            });
        }

    }

    private onViewLoaded(view: Views, prefab?: Prefab) {
        if (!view) return;
        let loading = this._loadingViewDic[view];
        if (prefab) loading.prefab = prefab;
        if (view != this._loadingViewQueue[0]) return;
        let baseView = this._viewDic[view] || this._viewCacheDic[view];
        if (!loading.prefab && !baseView) return;

        if (!baseView) {
            let viewNode = instantiate(loading.prefab);
            baseView = viewNode.getComponent(BaseView as any);
            if (!baseView) {
                viewNode.destroy();
                this.clearLoadingView(view);
                this.openNext();
                return errorMgr.error("界面打开失败：界面节点没有挂载BaseView组件");
            }
        }

        this._viewDic[view] = baseView;
        if (!baseView.isClosing) {
            this.clearLoadingView(view);
            layerMgr.getLayer(loading.layer).addChild(baseView.node);
            baseView.doOpen(loading.layer, loading.args);
            loading.onOpen && loading.onOpen(baseView);
        }
        this.openNext();
    }

    private openNext() {
        this.onViewLoaded(this._loadingViewQueue[0]);
    }

    private clearLoadingView(view: Views) {
        if (this._loadingViewDic[view]) {
            delete this._loadingViewDic[view];
            this._loadingViewQueue.splice(this._loadingViewQueue.indexOf(view), 1);
        }
    }

    /**
     * 关闭界面
     * @param view 
     */
    close(view: Views) {
        this.clearLoadingView(view);
        let baseView = this._viewDic[view];
        if (baseView) {
            baseView.doClose();
            delete this._viewDic[view];
            this._viewCacheDic[view] = baseView;
            this.openNext();
        }
    }

    /**
     * 关闭所有界面
     * @param exView 排除界面
     * @param layer 指定层级
     */
    closeAll(exView?: BaseView, layer?: ViewLayer) {
        if (exView) {
            for (let view in this._viewDic) {
                if (this._closeAllExViews[view]) continue;
                let baseView = this._viewDic[view];
                if (baseView === exView) continue;
                baseView.close();
            }
        } else if (layer) {
            for (let view in this._viewDic) {
                if (this._closeAllExViews[view]) continue;
                let baseView = this._viewDic[view];
                if (baseView.layer !== layer) continue;
                baseView.close();
            }
        } else {
            for (let view in this._viewDic) {
                this.close(view as Views);
            }
        }
    }

}

/**
 * 界面层级
 */
export enum ViewLayer {
    /** 主UI层 */
    Main,
    /** 一级窗口层 */
    Window,
    /** 二级窗口层 */
    WindowMid,
    /** 三级窗口层 */
    windowTop,
    /** alert层 */
    Alert,
    /** tip层 */
    Tip,
}